package com.blog.cmrpersonalblog.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.blog.cmrpersonalblog.dto.comment.request.CommentBatchOperationRequest;
import com.blog.cmrpersonalblog.dto.comment.request.CommentQueryRequest;
import com.blog.cmrpersonalblog.dto.comment.request.LatestCommentsRequest;
import com.blog.cmrpersonalblog.dto.comment.request.PopularCommentsRequest;
import com.blog.cmrpersonalblog.dto.comment.responst.CommentManagementResponse;
import com.blog.cmrpersonalblog.dto.sensitiveword.requset.SensitiveWordCheckResult;
import com.blog.cmrpersonalblog.entity.Comment;
import com.blog.cmrpersonalblog.mapper.ArticleMapper;
import com.blog.cmrpersonalblog.mapper.CommentMapper;
import com.blog.cmrpersonalblog.service.CommentImageService;
import com.blog.cmrpersonalblog.service.CommentManagementService;
import com.blog.cmrpersonalblog.service.SensitiveWordService;
import com.blog.cmrpersonalblog.service.UserActivityService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 评论管理服务实现类
 */
@Slf4j
@Service
public class CommentManagementServiceImpl implements CommentManagementService {

   @Resource
    private CommentMapper commentMapper;

   @Resource
    private ArticleMapper articleMapper;

   @Resource
    private SensitiveWordService sensitiveWordService;

   @Resource
    private UserActivityService userActivityService;

   @Resource
    private CommentImageService commentImageService;

   @Resource
    private com.blog.cmrpersonalblog.mapper.UserStatsMapper userStatsMapper;

    @Override
    public IPage<CommentManagementResponse> getCommentList(CommentQueryRequest queryRequest) {
        Page<CommentManagementResponse> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        return commentMapper.selectCommentManagementPage(page, queryRequest);
    }

    @Override
    public CommentManagementResponse getCommentDetail(Long commentId) {
        if (commentId == null) {
            return null;
        }
        return commentMapper.selectCommentDetailById(commentId);
    }

    @Override
    public List<CommentManagementResponse> getCommentTree(Long articleId, Long rootId) {
        if (articleId == null) {
            return new ArrayList<>();
        }
        
        List<CommentManagementResponse> comments = commentMapper.selectCommentTree(articleId, rootId);
        return buildCommentTree(comments);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createComment(Comment comment) {
        try {
            // 自动处理敏感词
            if (comment.getContent() != null && !comment.getContent().trim().isEmpty()) {
                SensitiveWordCheckResult checkResult = sensitiveWordService.checkSensitiveWords(comment.getContent());

                // 保存原始内容
                comment.setOriginalContent(comment.getContent());

                // 设置敏感词信息
                comment.setIsSensitive(checkResult.isHasSensitiveWords() ? 1 : 0);
                comment.setSensitiveScore(checkResult.getSensitiveScore());

                if (checkResult.isHasSensitiveWords()) {
                    // 检查是否有BLOCK模式的敏感词
                    if ("BLOCK".equals(checkResult.getSuggestedAction())) {
                        // 直接拦截，不允许发布
                        @SuppressWarnings("unchecked")
                        List<String> blockedWords = (List<String>) checkResult.getDetails().get("blockedWords");
                        String blockedWordsStr = blockedWords != null ? String.join(", ", blockedWords) : "未知敏感词";
                        log.warn("评论包含严重敏感词被拦截，用户ID：{}，敏感词：{}", comment.getUserId(), blockedWordsStr);
                        throw new RuntimeException("评论包含严重敏感词，不允许发布：" + blockedWordsStr);
                    }

                    comment.setSensitiveType(checkResult.getPrimaryType());
                    // 将敏感词列表转换为JSON字符串
                    if (checkResult.getSensitiveWords() != null) {
                        StringBuilder wordsJson = new StringBuilder("[");
                        for (int i = 0; i < checkResult.getSensitiveWords().size(); i++) {
                            if (i > 0) wordsJson.append(",");
                            SensitiveWordCheckResult.SensitiveWord word = checkResult.getSensitiveWords().get(i);
                            wordsJson.append("{\"word\":\"").append(word.getWord())
                                    .append("\",\"type\":\"").append(word.getType())
                                    .append("\",\"severity\":").append(word.getSeverity()).append("}");
                        }
                        wordsJson.append("]");
                        comment.setSensitiveWords(wordsJson.toString());
                    }

                    // 使用过滤后的内容（REPLACE模式）
                    comment.setContent(checkResult.getFilteredContent());
                    log.info("评论敏感词已过滤，用户ID：{}，原始长度：{}，过滤后长度：{}",
                            comment.getUserId(), comment.getOriginalContent().length(), comment.getContent().length());
                }
            }

            // 设置评论状态为正常显示
            comment.setStatus(1);

            // 保存评论
            int result = commentMapper.insert(comment);
            if (result > 0) {
                // 重新计算文章评论数量（基于实际评论数）
                try {
                    articleMapper.recalculateArticleCommentCount(comment.getArticleId());
                    log.debug("文章评论数量已重新计算: articleId={}", comment.getArticleId());
                } catch (Exception e) {
                    log.error("重新计算文章评论数量失败: articleId={}", comment.getArticleId(), e);
                    // 不影响评论创建，只记录错误
                }

                // 更新文章作者的用户统计 - 总评论数
                try {
                    com.blog.cmrpersonalblog.entity.Article article = articleMapper.selectById(comment.getArticleId());
                    if (article != null) {
                        userStatsMapper.updateUserStats(article.getAuthorId(), "total_comment_count", 1);
                        log.debug("更新作者统计评论数: authorId={}", article.getAuthorId());
                    }
                } catch (Exception e) {
                    log.warn("更新用户统计评论数失败: articleId={}", comment.getArticleId(), e);
                }

                log.info("评论创建成功: commentId={}, hasSensitive={}", comment.getId(), comment.getIsSensitive());
                return true;
            }

            return false;
        } catch (Exception e) {
            log.error("创建评论失败", e);
            throw new RuntimeException("创建评论失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> batchOperateComments(CommentBatchOperationRequest batchRequest, Long operatorId) {
        Map<String, Object> result = new HashMap<>();
        List<String> successIds = new ArrayList<>();
        List<String> failedIds = new ArrayList<>();
        
        try {
            if (!batchRequest.isValidOperationType()) {
                throw new RuntimeException("无效的操作类型");
            }

            CommentBatchOperationRequest.OperationType operationType = batchRequest.getOperationTypeEnum();
            int affectedRows = 0;

            switch (operationType) {
                case DELETE:
                    // 批量删除前，先获取相关的文章ID列表
                    List<Long> affectedArticleIds = commentMapper.selectArticleIdsByCommentIds(batchRequest.getCommentIds());
                    affectedRows = commentMapper.batchDeleteComments(batchRequest.getCommentIds());
                    
                    // 删除成功后，重新计算相关文章的评论数
                    if (affectedRows > 0 && !affectedArticleIds.isEmpty()) {
                        for (Long articleId : affectedArticleIds) {
                            try {
                                articleMapper.recalculateArticleCommentCount(articleId);
                                log.debug("重新计算文章评论数量: articleId={}", articleId);
                            } catch (Exception e) {
                                log.error("重新计算文章评论数量失败: articleId={}", articleId, e);
                            }
                        }
                    }
                    break;
                case MARK_SENSITIVE:
                    affectedRows = commentMapper.batchUpdateSensitiveStatus(
                        batchRequest.getCommentIds(), 1, batchRequest.getSensitiveType());
                    break;
                case UNMARK_SENSITIVE:
                    affectedRows = commentMapper.batchUpdateSensitiveStatus(
                        batchRequest.getCommentIds(), 0, null);
                    break;
                default:
                    throw new RuntimeException("不支持的操作类型: " + operationType.getDescription());
            }

            // 记录操作结果
            if (affectedRows > 0) {
                for (Long commentId : batchRequest.getCommentIds()) {
                    successIds.add(commentId.toString());
                }
                
                // 记录批量操作活动
                userActivityService.recordActivity(operatorId, "BATCH_COMMENT_OPERATION", 
                    "批量操作评论: " + operationType.getDescription(),
                    null, "comment", "SUCCESS", 
                    Map.of("operation", operationType.getCode(), "count", affectedRows));
                
                log.info("批量操作评论成功: operation={}, count={}, operatorId={}", 
                    operationType.getCode(), affectedRows, operatorId);
            }

            result.put("success", true);
            result.put("message", "批量操作完成");
            result.put("affectedRows", affectedRows);
            result.put("successIds", successIds);
            result.put("failedIds", failedIds);
            
        } catch (Exception e) {
            log.error("批量操作评论失败", e);
            result.put("success", false);
            result.put("message", "批量操作失败: " + e.getMessage());
            result.put("affectedRows", 0);
            result.put("successIds", successIds);

            // 避免使用方法引用，改为传统的循环方式
            List<String> failedIdStrings = new ArrayList<>();
            for (Long commentId : batchRequest.getCommentIds()) {
                failedIdStrings.add(commentId.toString());
            }
            result.put("failedIds", failedIdStrings);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteComment(Long commentId, Long operatorId) {
        try {
            Comment comment = commentMapper.selectById(commentId);
            if (comment == null) {
                throw new RuntimeException("评论不存在");
            }

            // 更新评论状态为已删除
            comment.setStatus(3);
            comment.setUpdateTime(LocalDateTime.now());
            
            int result = commentMapper.updateById(comment);
            if (result > 0) {
                // 记录删除活动
                userActivityService.recordActivity(operatorId, "COMMENT_DELETED", "删除评论",
                    commentId, "comment", "SUCCESS", null);
                
                log.info("评论删除成功: commentId={}, operatorId={}", commentId, operatorId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("评论删除失败", e);
            throw new RuntimeException("评论删除失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean restoreComment(Long commentId, Long operatorId) {
        try {
            Comment comment = commentMapper.selectById(commentId);
            if (comment == null) {
                throw new RuntimeException("评论不存在");
            }
            if (comment.getStatus() != 3) {
                throw new RuntimeException("只能恢复已删除的评论");
            }

            // 恢复评论状态为待审核
            comment.setStatus(0);
            comment.setUpdateTime(LocalDateTime.now());
            
            int result = commentMapper.updateById(comment);
            if (result > 0) {
                // 记录恢复活动
                userActivityService.recordActivity(operatorId, "COMMENT_RESTORED", "恢复评论",
                    commentId, "comment", "SUCCESS", null);
                
                log.info("评论恢复成功: commentId={}, operatorId={}", commentId, operatorId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("评论恢复失败", e);
            throw new RuntimeException("评论恢复失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markSensitive(Long commentId, String sensitiveType, Long operatorId) {
        try {
            Comment comment = commentMapper.selectById(commentId);
            if (comment == null) {
                throw new RuntimeException("评论不存在");
            }

            // 标记为敏感评论
            comment.setIsSensitive(1);
            comment.setSensitiveType(sensitiveType);
            comment.setUpdateTime(LocalDateTime.now());
            
            int result = commentMapper.updateById(comment);
            if (result > 0) {
                // 记录标记活动
                userActivityService.recordActivity(operatorId, "COMMENT_MARKED_SENSITIVE", "标记敏感评论",
                    commentId, "comment", "SUCCESS", Map.of("sensitiveType", sensitiveType));
                
                log.info("评论标记敏感成功: commentId={}, type={}, operatorId={}", commentId, sensitiveType, operatorId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("评论标记敏感失败", e);
            throw new RuntimeException("评论标记敏感失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unmarkSensitive(Long commentId, Long operatorId) {
        try {
            Comment comment = commentMapper.selectById(commentId);
            if (comment == null) {
                throw new RuntimeException("评论不存在");
            }

            // 取消敏感标记
            comment.setIsSensitive(0);
            comment.setSensitiveType(null);
            comment.setSensitiveWords(null);
            comment.setSensitiveScore(0);
            comment.setUpdateTime(LocalDateTime.now());
            
            int result = commentMapper.updateById(comment);
            if (result > 0) {
                // 记录取消标记活动
                userActivityService.recordActivity(operatorId, "COMMENT_UNMARKED_SENSITIVE", "取消敏感标记",
                    commentId, "comment", "SUCCESS", null);
                
                log.info("评论取消敏感标记成功: commentId={}, operatorId={}", commentId, operatorId);
                return true;
            }
            
            return false;
        } catch (Exception e) {
            log.error("评论取消敏感标记失败", e);
            throw new RuntimeException("评论取消敏感标记失败: " + e.getMessage());
        }
    }

    @Override
    public SensitiveWordCheckResult checkCommentSensitiveWords(String content) {
        return sensitiveWordService.checkSensitiveWords(content);
    }



    @Override
    public Map<String, Object> getCommentStatistics() {
        return commentMapper.selectCommentStatistics();
    }



    @Override
    public Long getSensitiveCommentCount() {
        return commentMapper.selectSensitiveCommentCount();
    }

    @Override
    public Map<String, Long> getCommentStatusDistribution() {
        List<Map<String, Object>> distribution = commentMapper.selectCommentStatusDistribution();
        Map<String, Long> result = new HashMap<>();

        for (Map<String, Object> item : distribution) {
            String statusName = (String) item.get("statusName");
            Long count = ((Number) item.get("count")).longValue();
            result.put(statusName, count);
        }

        return result;
    }

    @Override
    public Map<String, Long> getSensitiveTypeDistribution() {
        List<Map<String, Object>> distribution = commentMapper.selectSensitiveTypeDistribution();
        Map<String, Long> result = new HashMap<>();

        for (Map<String, Object> item : distribution) {
            String typeName = (String) item.get("typeName");
            Long count = ((Number) item.get("count")).longValue();
            result.put(typeName, count);
        }

        return result;
    }

    @Override
    public IPage<CommentManagementResponse> getLatestComments(LatestCommentsRequest request) {
        Page<CommentManagementResponse> page = new Page<>(request.getCurrent(), request.getSize());
        return commentMapper.selectLatestCommentsPage(page, request);
    }

    @Override
    public IPage<CommentManagementResponse> getPopularComments(PopularCommentsRequest request) {
        Page<CommentManagementResponse> page = new Page<>(request.getCurrent(), request.getSize());
        return commentMapper.selectPopularCommentsPage(page, request);
    }

    @Override
    public IPage<CommentManagementResponse> searchComments(String keyword, Long current, Long size) {
        Page<CommentManagementResponse> page = new Page<>(current != null ? current : 1L, size != null ? size : 10L);
        return commentMapper.searchComments(page, keyword);
    }

    @Override
    public IPage<CommentManagementResponse> getUserComments(Long userId, Long current, Long size) {
        Page<CommentManagementResponse> page = new Page<>(current != null ? current : 1L, size != null ? size : 10L);
        return commentMapper.selectUserCommentManagementPage(page, userId);
    }

    @Override
    public IPage<CommentManagementResponse> getArticleComments(Long articleId, Long current, Long size) {
        Page<CommentManagementResponse> page = new Page<>(current != null ? current : 1L, size != null ? size : 10L);
        return commentMapper.selectArticleCommentManagementPage(page, articleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCommentStats(Long commentId, String field, Integer increment) {
        try {
            commentMapper.updateCommentStats(commentId, field, increment);
            return true;
        } catch (Exception e) {
            log.error("更新评论统计数据失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recalculateCommentStats(Long commentId) {
        try {
            int result = commentMapper.recalculateCommentStats(commentId);
            return result > 0;
        } catch (Exception e) {
            log.error("重新计算评论统计数据失败", e);
            return false;
        }
    }

    @Override
    public String buildCommentPath(Comment comment) {
        if (comment.isTopLevel()) {
            return comment.getId().toString();
        }
        
        String parentPath = commentMapper.selectCommentPath(comment.getParentId());
        return parentPath != null ? parentPath + "/" + comment.getId() : comment.getId().toString();
    }

    @Override
    public List<Long> getAllChildCommentIds(Long commentId) {
        return commentMapper.selectAllChildCommentIds(commentId);
    }

    @Override
    public IPage<CommentManagementResponse> getCommentsByIpAddress(String ipAddress, Long current, Long size) {
        Page<CommentManagementResponse> page = new Page<>(current != null ? current : 1L, size != null ? size : 10L);
        return commentMapper.selectCommentsByIpAddress(page, ipAddress);
    }

    /**
     * 构建评论树形结构
     */
    private List<CommentManagementResponse> buildCommentTree(List<CommentManagementResponse> comments) {
        if (comments == null || comments.isEmpty()) {
            return new ArrayList<>();
        }

        // 按ID分组，便于查找 - 避免使用方法引用
        Map<Long, CommentManagementResponse> commentMap = new HashMap<>();
        for (CommentManagementResponse comment : comments) {
            commentMap.put(comment.getId(), comment);
        }

        List<CommentManagementResponse> rootComments = new ArrayList<>();

        for (CommentManagementResponse comment : comments) {
            if (comment.isTopLevel()) {
                rootComments.add(comment);
            } else {
                CommentManagementResponse parent = commentMap.get(comment.getParentId());
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(comment);
                    comment.setParent(parent);
                }
            }
        }

        return rootComments;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean hardDeleteComment(Long commentId, Long operatorId) {
        log.info("管理员硬删除评论: commentId={}, operatorId={}", commentId, operatorId);
        
        // 检查评论是否存在
        Comment comment = commentMapper.selectById(commentId);
        if (comment == null) {
            throw new RuntimeException("评论不存在");
        }
        
        // 在删除评论前，先将相关图片状态设置为已删除
        try {
            commentImageService.updateCommentImagesStatus(commentId, 0);
            log.info("评论图片状态已更新为已删除: commentId={}", commentId);
        } catch (Exception e) {
            log.error("更新评论图片状态失败: commentId={}", commentId, e);
            // 继续执行评论删除，即使图片状态更新失败
        }
        
        // 硬删除评论（只删除单个评论，不删除子评论）
        int deleted = commentMapper.hardDeleteComment(commentId);
        
        if (deleted > 0) {
            // 更新文章评论数量
            try {
                articleMapper.recalculateArticleCommentCount(comment.getArticleId());
                log.debug("重新计算文章评论数量: articleId={}", comment.getArticleId());
            } catch (Exception e) {
                log.error("重新计算文章评论数量失败: articleId={}", comment.getArticleId(), e);
            }

            // 更新文章作者的用户统计 - 总评论数
            try {
                com.blog.cmrpersonalblog.entity.Article article = articleMapper.selectById(comment.getArticleId());
                if (article != null) {
                    userStatsMapper.updateUserStats(article.getAuthorId(), "total_comment_count", -1);
                    log.debug("更新作者统计评论数: authorId={}", article.getAuthorId());
                }
            } catch (Exception e) {
                log.warn("更新用户统计评论数失败: articleId={}", comment.getArticleId(), e);
            }

            // 如果是回复评论，重新计算父评论的回复数
            if (comment.getParentId() != null && comment.getParentId() > 0) {
                try {
                    recalculateCommentStats(comment.getParentId());
                } catch (Exception e) {
                    log.error("重新计算父评论回复数失败: parentId={}", comment.getParentId(), e);
                }
            }

            log.info("评论硬删除成功: commentId={}", commentId);
        }
        
        return deleted > 0;
    }
}
